package be.artesis.titamo.io;


/**
 * Contains all content regarding a time table entry. This class is also used for the
 * webservice and the parser. So it contains all possible data regarding a timetable-entry.
 * 
 * @author 	Sander Eskens
 *
 * @see		be.artesis.titamo.io.TimeTableDataFile
 */
public class TimeTableEntry {

	// Regular expression to know whether a string is an hour or not.
	public final static String TIME_REGEX = "^[0-9]?[0-9][u:h][0-9][0-9]$";
	public final static String ERROR_DELIMITER = "\n";
	
	// All relevant fields containing data from the entry of the database
	private int id;
	private String duration;
	private String classroom;
	private String classgroup;
	private String start;
	private String instructor;
	private String course;
	private int day;
	
	// Fields regarding an invalid entry (with explanation of why is has become invalid)
	private boolean valid;
	private String error;
	// these last two are only set when reading from database
	private String filename;
	private int linenumber;
	
	/**
	 * Basic constructor. Nothing needs to be set here so that while traversing or parsing the data the
	 * field can be set each at a time.
	 */
	public TimeTableEntry()
	{
		this.valid = true;
		this.error = "";
	}
	
	/**
	 * Sets the id-field of the entry. While parsing used to determine the line number. And when traversing the database
	 * resultset used for the database-id.
	 * @param	id		the id that must be set
	 */
	public void setID(int id)
	{
		this.id = id;
	}
	
	/**
	 * Gets the ID of the entry.
	 * @return	int 	the id is returned
	 */
	public int getID()
	{
		return this.id;
	}
	
	/**
	 * Sets the duration of the entry.
	 * @param	duration	the duration that must be set. It is important that duration matches the time-regex. 
	 * 						Otherwise the entry is set invalid.
	 */
	public void setDuration(String duration) {
		this.duration = duration;
		if (!this.duration.matches(TIME_REGEX)) this.addError("Duration has an invalid time-syntax: " + this.duration + " is invalid.");
	}

	/**
	 * Gets the duration of the entry.
	 * @return 	String	the duration in the format used by the setDuration() method.	
	 */
	public String getDuration() {
		return this.duration;
	}

	/**
	 * Sets the classroom of the entry.
	 * @param 	classroom	the room that must be set.
	 */
	public void setRoom(String classroom) {
		this.classroom = classroom;
	}

	/**
	 * Gets the classroom of the entry.
	 * @return	String	containing the id of classroom.
	 */
	public String getRoom() {
		return this.classroom;
	}

	/**
	 * Sets the group of students (class) of the entry.
	 * @param  classgroup	the group that must be set
	 */
	public void setGroup(String classgroup) {
		this.classgroup = classgroup;
	}

	/**
	 * Gets the group of students (class) of the entry
	 * @return	String	containing the group.
	 */
	public String getGroup() {
		return this.classgroup;
	}

	/**
	 * Sets the start time of the entry.
	 * @param 	start	start time which must match the regex for a time-String. 
	 * 					Otherwise the entry is set invalid.
	 */
	public void setStart(String start) {
		this.start = start;
		if (!this.start.matches(TIME_REGEX)) this.addError("Start has an invalid time-syntax: " + this.start + " is invalid.");
	}

	/**
	 * Gets the start time of the entry.
	 * @return	String	contains the Start time of the entry
	 */
	public String getStart() {
		return this.start;
	}

	/**
	 * Sets the instructor of the entry.
	 * @param	instructor	the instructors name to be set.
	 */
	public void setInstructor(String instructor) {
		this.instructor = instructor;
	}

	/**
	 * Gets the instructor of the entry.
	 * @return	String	containing the name(s) of the instructors.
	 */
	public String getInstructor() {
		return this.instructor;
	}

	/**
	 * Sets the course of the entry.
	 * @param	course	the name of the course that must be set.
	 */
	public void setCourse(String course) {
		this.course = course;
	}

	/**
	 * Gets the name of the course.
	 * @return	String	containing the name of the course.
	 */
	public String getCourse() {
		return this.course;
	}

	/**
	 * Sets the day of the entry.
	 * @param	day		the day that must be set.
	 */
	public void setDay(int day) {
		this.day = day;
	}

	/**
	 * Gets the day of the entry.
	 * @return	String	containing the day of the entry.
	 */
	public int getDay() {
		return day;
	}
	
	/**
	 * Sets the linenumber of the entry. Only useful when parsing data out of a database. Otherwise use setID().
	 * @param	linenumber	the linenumber in the original file this was parsed.
	 */
	public void setLine(int linenumber) {
		this.linenumber = linenumber;
	}

	/**
	 * Gets the linenumber were the error was found.
	 * @return	int		the linenumber containing the fault.
	 */
	public int getLine() {
		return linenumber;
	}

	/**
	 * Sets the filename of the entry. Only useful when parsing invalid data out of a database. Otherwise
	 * TimeTableDataFile contains the filename ofcourse.
	 * @param	filename	the filename that must be set.
	 */
	public void setFilename(String filename) {
		this.filename = filename;
	}

	/**
	 * Gets the filename of the entry.
	 * @return	String	contains the name of the original file the error was found in.
	 */
	public String getFilename() {
		return filename;
	}
	
	/**
	 * Checks whether a number of fields are set. Useful after parsing a full line.
	 * @return	boolean	whether or not the entry is valid when returned.
	 */
	public boolean check()
	{
		if (getStart() == null) {
			this.addError("No start time was found.");
		}
		if (getDuration() == null) {
			this.addError("No duration time was found");
		}
		if (getDay() < 0) {
			this.addError("No day was found.");
		}
		return this.isValid();
	}
	
	/**
	 * Adds an error to the errorfield with the delimiter. This will also set the entry invalid.
	 * @param	error	the error message to add to the list.
	 */
	private void addError(String error)
	{
		this.setInvalid();
		this.error += error + ERROR_DELIMITER;
	}
	
	/**
	 * Sets the entry invalid.
	 */
	private void setInvalid()
	{
		this.valid = false;
	}
	
	/**
	 * Checks whether the entry is valid or not
	 * @return	boolean		return "true" if the entry is valid. "false" when invalid.
	 */
	public boolean isValid()
	{
		return this.valid;
	}
	
	/**
	 * Gets the errors of the entry.
	 * @return	String[]	array of strings containing the error messages of the entry.
	 */
	public String[] getErrors() 
	{
		return error.split(ERROR_DELIMITER);
	}
	
	/**
	 * Gets the errors in one string using a seperator
	 * @param seperator	the seperator to use.
	 * @return	String	contains the errors info.
	 */
	public String getErrorString(String seperator)
	{
		String e = "";
		for (String error: getErrors())
		{
			e += error + seperator;
		}
		return e.trim();
	}
	
	/**
	 * Gets all data from the error-field of the entry.
	 * @return	String	contains all data of errors.
	 */
	public String getError()
	{
		return this.error;
	}
	
	/**
	 * Sets the error field of the entry.
	 * @param 	error	the error that must be set.
	 */
	public void setError(String error)
	{
		this.setInvalid();
		this.error = error;
	}
	
	@Override
	public String toString()
	{
		String s = "TimeTableEntry:\n";
		if (this.isValid())
		{
			s += 	"\tid: " + getID() +
					"\n\tday: " + getDay() +
					"\n\tstart: " + getStart() +
					"\n\tduration: " + getDuration() +
					"\n\tcourse: " + getCourse() +
					"\n\tinstructor: " + getInstructor() +
					"\n\tgroup: " + getGroup() +
					"\n\troom: " + getRoom();
		} 
		else
		{
			s += "\tinvalid entry:\n";
			for (String error : getErrors())
			{
				s += "\t\t" + error + "\n";
			}
		}
		return s.trim();
	}
}
